package com.mastercard.assets.flows;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import com.mastercard.assets.MasterCardException;
import com.mastercard.assets.flows.process.FlowProcess;
import com.mastercard.assets.flows.process.FlowProcessContext;
import com.mastercard.assets.flows.process.FlowProcessInit;
import com.mastercard.assets.flows.process.FlowProcessPost;
import com.mastercard.assets.flows.process.FlowProcessPrevious;
import com.mastercard.assets.flows.process.FlowProcessResult;
import com.mastercard.assets.flows.to.FlowDataTO;
import com.mastercard.assets.flows.to.FlowPreimplementationTO;
import com.mastercard.assets.jpa.TblAsset;
import com.mastercard.assets.jpa.TblFlujo;
import com.mastercard.assets.jpa.TblForma;
import com.mastercard.assets.jpa.TblPreimplementacion;
import com.mastercard.assets.jpa.TblTarea;
import com.mastercard.assets.jpa.TblTareaFlujo;
import com.mastercard.assets.jpa.TblTareaPreimplementacion;
import com.mastercard.assets.util.MCUtil;
import com.mastercard.assets.util.dao.MasterCardDAO;
import com.mastercard.assets.web.struts.forms.FlowProcessForm;
import com.mastercard.assets.web.util.to.UserLogin;

public class FlowUtil
	implements
		java.io.Serializable
{
	public static final int FLOW_CONSTANTS_FORM_PROCESS_CAN_DISPLAY = 1 ;
	public static final int FLOW_CONSTANTS_FORM_PROCESS_WORK_FLOW_EXECUTED = 2 ;
	public static final int FLOW_CONSTANTS_FORM_PROCESS_WORK_FLOW_WORK_DESACTIVATED = 3 ;
	public static final int FLOW_CONSTANTS_FORM_PROCESS_WORK_FLOW_WORK_FORM_DESACTIVATED = 4 ;
	public static final int FLOW_CONSTANTS_FORM_PROCESS_DATA_PROCESS_SUCCESS = 5 ;
	public static final int FLOW_CONSTANTS_FORM_PROCESS_DATA_PROCESS_ERROR_RELOAD = 6 ;
	public static final int FLOW_CONSTANTS_FORM_PROCESS_DATA_PROCESS_ERROR_DISPLAY_ERROR_PAGE = 7 ;
	public static final int FLOW_CONSTANTS_FORM_PROCESS_DATA_PROCESS_NO_FORM_FILE_EXIST = 8 ;
	public static final int FLOW_CONSTANTS_FORM_PROCESS_DATA_PROCESS_ERROR_OBTAINING_PATH = 9 ;
	
	public static final int FLOW_SETUP_WORK_RESULT_SAVE_NEXT_WORK = 1 ;
	public static final int FLOW_SETUP_WORK_RESULT_LAST_WORK_IN_FLOW = 2 ;
	
	public static FlowDataTO preProcessForm( FlowProcessContext ctx )
		throws
			MasterCardException
	{
		TblTareaPreimplementacion tblTareaPreimplementacion = MasterCardDAO.findTareaPreimplementacionById( ctx.getCveTareaPreimplementacion( ) ) ;
		
		System.out.println( "FlowUtil.java: loadFormData/1" ) ;
		
		// en caso de null
		if( tblTareaPreimplementacion == null )
			throw new MasterCardException( 
					MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.flows.display.WorkFlowNotExist" , ctx.getCveTareaPreimplementacion( ) ) ,
					MCUtil.MASTERCARD_ERROR_CODE_FLOWS_WORK_FLOW_NOT_EXITS , 
					null ) ;
		
		System.out.println( "FlowUtil.java: loadFormData/2" ) ;
		
		// toma las clases para procesar la forma antes de desplegarla
		// toma la tarea
		TblTarea tarea = tblTareaPreimplementacion.getTblTarea( ) ;
		
		MasterCardDAO.refresh( tarea ) ;
		
		System.out.println( "FlowUtil.java: loadFormData/3" + tarea ) ;
		
		// en caso de null
		if( tarea == null )
			throw new MasterCardException( 
					MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.flows.display.WorkFlowWithoutWork" , ctx.getCveTareaPreimplementacion( ) ) ,
					MCUtil.MASTERCARD_ERROR_CODE_FLOWS_WORK_FLOW_WITHOUT_WORK , 
					null ) ;
		
//		MasterCardDAO.refresh( tarea ) ;
//		
		String nombreTarea = tarea.getNombre( ) ;
		
		System.out.println( "FlowUtil.java: loadFormData/4" + nombreTarea ) ;
		
		// toma la forma a la que esta ligada la tarea
		TblForma forma = tarea.getTblForma( ) ;
		
		MasterCardDAO.refresh( forma ) ;
		
		// en caso de que este null
		if( forma == null )
			throw new MasterCardException( 
					MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.flows.display.WorkFlowWorkWithoutForm" , nombreTarea ) ,
					MCUtil.MASTERCARD_ERROR_CODE_FLOWS_WORK_FLOW_WORK_WITHOUT_FORM , 
					null ) ;
		
//		MasterCardDAO.refresh( forma ) ;
//		
		// toma la clase que se ejectua para verificar si la forma se puede desplegar
		String initClassString = forma.getInitClass( ) ;
		
		String nombreForma = forma.getNombre( ) ;
		
		System.out.println( "FlowUtil.java: loadFormData/5" + nombreForma ) ;
		
		if( nombreForma == null || nombreForma.trim( ).length( ) == 0 )
			nombreForma = "Forma-Sin-Nombre" ;
		
		// en caso de que este en null o vacio
		if( initClassString == null || initClassString.trim( ).length( ) == 0 )
			throw new MasterCardException( 
					MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.flows.display.WorkFlowWorkFormInitClassIsEmpty" , nombreForma ) ,
					MCUtil.MASTERCARD_ERROR_CODE_FLOWS_WORK_FLOW_WORK_FORM_WITHOUT_INIT_CLASS , 
					null ) ;
		
		System.out.println( "FlowUtil.java: loadFormData/6" + initClassString ) ;
		
		// en caso de que si exista
		// verifica si se encuentra dentro del classpath y la instancia
		Class initClass = null ;
		FlowProcessInit processInit = null ;
		try
		{
			initClass = Class.forName( initClassString ) ;
			processInit = ( FlowProcessInit ) initClass.newInstance( ) ;
			System.out.println( "FlowUtil.java: loadFormData/7" ) ;
			
		}catch( Exception e )
		{
                    MasterCardDAO.closeEntityManager( ) ;
			e.printStackTrace( ) ;
			throw new MasterCardException( 
					MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.flows.display.WorkFlowWorkFormInitClassErrorOnLoading" , nombreForma ) ,
					MCUtil.MASTERCARD_ERROR_CODE_FLOWS_WORK_FLOW_WORK_FORM_ERROR_LOADING_INIT_CLASS , 
					e ) ;
		}
		
		// en caso de que se haya iniciado verifica si se puede cargar el formulario
		FlowProcessResult res = processInit.canDisplay( ctx ) ;
		
		System.out.println( "FlowUtil.java: loadFormData/8" + res ) ;
		
		switch( res.getResult( ) )
		{
			// en caso de uqe ya este ejecutado
			case FlowUtil.FLOW_CONSTANTS_FORM_PROCESS_WORK_FLOW_EXECUTED :
				
				if( tblTareaPreimplementacion.getEjecutado( ) == 1 )
					throw new MasterCardException( 
							MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.flows.display.WorkFlowAlreadyExecuted" , ctx.getCveTareaPreimplementacion( ) ) ,
							MCUtil.MASTERCARD_ERROR_CODE_FLOWS_WORK_FLOW_ALREADY_EXECUTED , 
							null ) ;
				
			// en caso de que la tarea haya sido desactivada
			case FlowUtil.FLOW_CONSTANTS_FORM_PROCESS_WORK_FLOW_WORK_DESACTIVATED :
				if( tarea.getStatus( ) == 0 )
					throw new MasterCardException( 
							MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.flows.display.WorkFlowWorkUnactivated" , ( nombreTarea == null ? "Tarea-Sin-Nombre" : nombreTarea ) ) ,
							MCUtil.MASTERCARD_ERROR_CODE_FLOWS_WORK_FLOW_WORK_UNACTIVATED , 
							null ) ;
				
				
			// en caso de que la forma este desactivada
			case FlowUtil.FLOW_CONSTANTS_FORM_PROCESS_WORK_FLOW_WORK_FORM_DESACTIVATED :
				if( forma.getStatus( ) == 0 )
					throw new MasterCardException( 
							MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.flows.display.WorkFlowWorkFormUnactivated" , nombreTarea ) ,
							MCUtil.MASTERCARD_ERROR_CODE_FLOWS_WORK_FLOW_WORK_FORM_UNACTIVATED , 
							null ) ;
				
			// en caso de que si se pueda cargar
			case FlowUtil.FLOW_CONSTANTS_FORM_PROCESS_CAN_DISPLAY :
				
				// toma la clase de previousClass, para cargar los datos
				// toma la clase que se ejectua para verificar si la forma se puede desplegar
				String previousClassString = forma.getInitClass( ) ;
				
				System.out.println( "FlowUtil.java: loadFormData/9" + previousClassString ) ;
				
				// verifica si se encuentra dentro del classpath y la instancia
				Class previousClass = null ;
				FlowProcessPrevious processPrevious = null ;
				try
				{
					previousClass = Class.forName( previousClassString ) ;
					processPrevious = ( FlowProcessPrevious ) initClass.newInstance( ) ;
					System.out.println( "FlowUtil.java: loadFormData/10" ) ;
					
				}catch( Exception e )
				{
                                    MasterCardDAO.closeEntityManager( ) ;
					throw new MasterCardException( 
							MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.flows.display.WorkFlowWorkFormPreviousClassErrorOnLoading" , nombreForma ) ,
							MCUtil.MASTERCARD_ERROR_CODE_FLOWS_WORK_FLOW_WORK_FORM_ERROR_LOADING_PREVIOUS_CLASS , 
							null ) ;
				}
			
				// toma los datos cargados
 				FlowProcessResult result = processPrevious.loadFormData( ctx ) ;
 				
 				// en caso de que haya error
 				switch( result.getResult( ) )
 				{
 					case FlowUtil.FLOW_CONSTANTS_FORM_PROCESS_DATA_PROCESS_NO_FORM_FILE_EXIST :
 						
 						throw new MasterCardException( 
 								result.getMessage( ) , 
 								MCUtil.MASTERCARD_ERROR_CODE_FLOWS_PROCESS_PREIMPLEMENTATION_FORM_FILE_NO_EXIST , 
 								result.getException( ) ) ;

 					case FlowUtil.FLOW_CONSTANTS_FORM_PROCESS_DATA_PROCESS_ERROR_OBTAINING_PATH :
 						
 						throw new MasterCardException( 
 								result.getMessage( ) , 
 								MCUtil.MASTERCARD_ERROR_CODE_FLOWS_PROCESS_PREIMPLEMENTATION_ERROR_OBTAINING_PATH , 
 								result.getException( ) ) ;
 				}
 				
				FlowDataTO to = result.getData( ) ;
				
				System.out.println( "FlowUtil.java: loadFormData/" + to ) ;
				MasterCardDAO.closeEntityManager( ) ;
				return to ;
				
		}
		MasterCardDAO.closeEntityManager( ) ;
		return null ;
	}
	
	public static void processExit( FlowProcessForm form , HttpServletRequest request )
		throws
			MasterCardException
	{
//		int tblTareaPreimplementacion = form.getCveWorkPreimplementation( ) ;
//		String exit = form.getExit( ) ;
//		String processClass = form.getProcessClass( ) ;
//		
//		// en caso de null o vacio
//		if( processClass == null || processClass.trim( ).length( ) == 0 )
//			throw new MasterCardException( 
//					MCUtil.messages.getString( "com.mastercard.assets.web.errors.dao.login.ProcessClassNotExist" ) , 
//					MCUtil.MASTERCARD_ERROR_CODE_FLOWS_PROCESS_CLASS_NOT_EXIST , 
//					null ) ;
//		
//		FlowProcess fp = null ;
//		
//		try
//		{
//			Class fpClass = Class.forName( processClass ) ;
//			
//			// la instancia
//			fp = ( FlowProcess ) fpClass.newInstance( ) ;
//			
//			// procesa la peticion
//			fp.processExit( form , request ) ;
//		}catch( Exception e )
//		{
//			throw new MasterCardException( 
//					MCUtil.messages.getString( "com.mastercard.assets.web.errors.dao.process.ProcessClassErrorProcess" , e.getMessage( ) ) , 
//					MCUtil.MASTERCARD_ERROR_CODE_FLOWS_PROCESS_ERROR , 
//					null ) ;
//		}
	}
	
	public static FlowProcessResult postProcessForm( FlowProcessContext ctx )
		throws
			MasterCardException
	{
		TblTareaPreimplementacion tblTareaPreimplementacion = ctx.getTblTareaPreimplementacion( ) ;
		
		// en caso de null
		if( tblTareaPreimplementacion == null )
			throw new MasterCardException( 
					MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.flows.display.WorkFlowNotExist" , ctx.getCveTareaPreimplementacion( ) ) ,
					MCUtil.MASTERCARD_ERROR_CODE_FLOWS_WORK_FLOW_NOT_EXITS , 
					null ) ;
		
		// toma las clases para procesar la forma antes de desplegarla
		// toma la tarea
		TblTarea tarea = tblTareaPreimplementacion.getTblTarea( ) ;
		
		// en caso de null
		if( tarea == null )
			throw new MasterCardException( 
					MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.flows.display.WorkFlowWithoutWork" , ctx.getCveTareaPreimplementacion( ) ) ,
					MCUtil.MASTERCARD_ERROR_CODE_FLOWS_WORK_FLOW_WITHOUT_WORK , 
					null ) ;
		
		MasterCardDAO.refresh( tarea ) ;
//		
		String nombreTarea = tarea.getNombre( ) ;
		
		// toma la forma a la que esta ligada la tarea
		TblForma forma = tarea.getTblForma( ) ;
		
		// en caso de que este null
		if( forma == null )
			throw new MasterCardException( 
					MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.flows.display.WorkFlowWorkWithoutForm" , nombreTarea ) ,
					MCUtil.MASTERCARD_ERROR_CODE_FLOWS_WORK_FLOW_WORK_WITHOUT_FORM , 
					null ) ;
		
//		MasterCardDAO.refresh( forma ) ;
		MasterCardDAO.closeEntityManager( ) ;
		// toma la clase que se ejectua para procesar la forma
		String postClassString = forma.getPostClass( ) ;
		
		String nombreForma = forma.getNombre( ) ;
		
		if( nombreForma == null || nombreForma.trim( ).length( ) == 0 )
			nombreForma = "Forma-Sin-Nombre" ;
		
		// en caso de que este en null o vacio
		if( postClassString == null || postClassString.trim( ).length( ) == 0 )
			throw new MasterCardException( 
					MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.flows.display.WorkFlowWorkFormPostClassIsEmpty" , nombreForma ) ,
					MCUtil.MASTERCARD_ERROR_CODE_FLOWS_WORK_FLOW_WORK_FORM_WITHOUT_POST_CLASS , 
					null ) ;
		
		// en caso de que si exista
		// verifica si se encuentra dentro del classpath y la instancia
		Class postClass = null ;
		FlowProcessPost processPost = null ;
		try
		{
			postClass = Class.forName( postClassString ) ;
			processPost = ( FlowProcessPost ) postClass.newInstance( ) ;
		}catch( Exception e )
		{
			throw new MasterCardException( 
					MCUtil.messages.getString( "com.mastercard.assets.web.errors.modules.flows.display.WorkFlowWorkFormPostClassErrorOnLoading" , nombreForma ) ,
					MCUtil.MASTERCARD_ERROR_CODE_FLOWS_WORK_FLOW_WORK_FORM_ERROR_LOADING_POST_CLASS , 
					null ) ;
		}
		
		// en caso de que se haya iniciado verifica si se puede cargar el formulario
		FlowProcessResult res = processPost.processExit(ctx) ;
		
		switch( res.getResult( ) )
		{
			// en caso de uqe ya este ejecutado
			case FlowUtil.FLOW_CONSTANTS_FORM_PROCESS_DATA_PROCESS_SUCCESS :
				
				FlowProcessForm form = ctx.getForm( ) ;
				UserLogin user = ctx.getUser( ) ;
				int cveUsuario = user.getCveUsuario( ) ;
				
				int cveTareaPreimplementacion = form.getCveWorkPreimplementation( ) ;
				
				String exit = form.getExit( ) ;
				
				int result = res.getStepupResult( ) ;
				
				return res ;
				
			case FlowUtil.FLOW_CONSTANTS_FORM_PROCESS_DATA_PROCESS_ERROR_RELOAD :
				
				return res ;
				
			default :
				
				return null ;
		}
		
	}
}
